package com.dale.shiro;

import cn.hutool.core.bean.BeanUtil;
import com.dale.entity.User;
import com.dale.mapper.RoleMapper;
import com.dale.service.UserService;
import com.dale.util.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class AccountRealm extends AuthorizingRealm {

    @Autowired
    JwtUtils jwtUtils;

    @Autowired
    UserService userService;

    @Autowired
    RoleMapper roleMapper;

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;   //是jwt则可以强转。。。
    }


    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

        //获取主身份信息 方式1 （来自下面的认证）
        AccountProfile primaryPrincipal =(AccountProfile) principals.getPrimaryPrincipal();

//        //方式二  自己写的哈   我也不知道为啥还需要自己写    接口处很多用  完全没必要哈
//        AccountProfile profile = ShiroUtil.getProfile();
//
//        //方式三(自带的)
//        AccountProfile principal = (AccountProfile)SecurityUtils.getSubject().getPrincipal();

//        log.info("调用授权");

        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();


        User user = userService.getById(primaryPrincipal.getId());

        String userRole = roleMapper.getUserRole(user.getId());


        simpleAuthorizationInfo.addRole(userRole);


        return simpleAuthorizationInfo;
    }

    /**
     *
     * 注意  所谓 登录的 概念
     *
     *
     */
    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        JwtToken jwtToken = (JwtToken) token;

        //token
        String principal = (String)jwtToken.getPrincipal();

//       log.info("调用认证");

        //通过token获得用户
        String userId = jwtUtils.getClaimByToken((String) (jwtToken.getPrincipal())).getSubject();

        User user = userService.getById(Long.valueOf(userId));
        if (user == null) {
            //由于在Controller中已经判断了 登录是否成功 所以这一步 永远不可能到来
            //哈哈哈 登录有两个概念 第一次登录   后面的状态验证通过shiro 处理 token 登录

            throw new UnknownAccountException("账户不存在");
        }

        if (user.getStatus() == 1) {

            log.info("账户已被锁定");

            throw new LockedAccountException("账户已被锁定");
        }

        //为了登录成功之后返回的一个用户信息的载体
        AccountProfile profile = new AccountProfile();

        //hutool工具将 数据库中的user信息 赋值给 profile
        BeanUtil.copyProperties(user, profile);



        //这里只进行了jwt的认证而没有 密码账户认证 所以 在controller层验证了密码和账号

        //这里  shiro自己进行了账户密码验证  确实有（就是简单的比对principle(AccountProfile)+Credentials(token))
        // 然后 我又在 接口处~~？ 或者说哪里说明覆盖了！错错，不是覆盖   接口处的验证
        // 以前就是UsernamePasswordToken  获得token  然后subject.login(token)实现登录 jwt的产生用了盐
        //
        //返回 认证信息 包括profile（用户信息）   token    realmName
        //然后就可以  通过SecurityUtils.getSubject().getPrincipal()   《该方法在ShiroUtil中  可以输出以下》  获取？？？  打个断点测试以下是不是这个顺序
        return new SimpleAuthenticationInfo(profile, jwtToken.getCredentials(), getName());
    }
}
